iT邦幫忙

2

React 學習筆記_4(可控組件(State)與不可控組件(Ref))

  • 分享至 

  • xImage
  •  

Ref

在典型的 React中,props 是 父層與子層唯一的互動方式。藉由使用新的 prop 重新 render 來改變你的子層。

什麼時候該使用 Ref

  • 管理 focus、選擇文字、影音播放。
  • 觸發即時的動畫
  • 與第三方 DOM 函式庫整合

不要過度使用 Ref

建立 Ref

class Login extends React.Component
{
    //建立Ref
    emailRef = React.createRef();
    passwordRef = React.createRef();
    
    //存取Ref
    const formData = {
        email:this.emailRef.current.value,
        passwordRef:this.passwordRef.current.value
    };
    
    render()
    {
        return(
            <input class="input" type="text" placeholder="Email" ref={this.emailRef}/>
            <input class="input" type="text" placeholder="Password" ref={this.passwordRef} />
        )
    }
};
export default Login;

state

重點

  • 通常會在component的 constructor 設定state初始值。
    1.使用constructor設定初始值
class Like extends React.Component
{
    constructor()
    {
        super();
        this.state = {
            isLike:false; //預設為false
        }
    }
}

2.使用state設定初始值

class Like extends React.Component
{
    state = {
        isLike:false //預設為false
    }
}
  • 要改變state,必須使用setState()。
class Like extends React.Component
{
    //設定預設值
    state = {
        isLike:false, //預設為false
        const:0 //預設const = 0
    }
    
    //建立Event Function
    handleClick() => {
        //取得當前狀況並對狀況進行處理
        this.setState({
            isLike: !this.state.isLike, //取得當前狀態並進行反轉
            const:this.state.const + 1 //取得當前狀況並+1
        });
        
        //若要取得上一個對象的狀態需要使用箭頭函數
        this.setState(prevState => {
            return{
                count : prevState.const + 2
            };
        });   
    };
    
    render()
    {
        return(
            <button className = "button is-fullwidth is-primary" onClick = {this.handleClick}>
                {this.state.isLike? "No":"Yes"}
            </button>
        )
    }
}

可控組件(Controlled component)與不可控組件(Uncontrolled component)

不可控組件(Uncontrolled component)

  • 如果要寫一個 uncontrolled component,你可以使用 ref 來從 DOM 取得表單的資料

由Ref取得input的Data,並當form的Submit被觸發後進入function "handleSubmit",將Ref中的data取出
(this.input.current.value)

class NameForm extends React.Component
{
    //建立constructor
    constructor()
    {
        super();
        //使用bind複製function handleSubmit並將this(自身class)指定給他,進行this綁定
        this.handleSubmit = this.handleSubmit.bind(this);
        //使用Ref取得input資料
        input = React.createRef();
    }
    
    handleSubmit = (event) =>{
        alert('A name was submitted: ' + this.input.current.value);
        //取消默認行為
        event.preventDefault();
    }
    
    render()
    {
        return(
            <form onSubmit={this.handleSubmit}>
                <label>Name:<input type="text" ref={this.input} /> </label>
                <input type="submit" value="Submit" />
            </form>
        );
    }
};
  • 預設值:在React的render生命週期裡,表單的"value attribute"會覆蓋掉DOM的值,在使用uncontrolled component會希望表單設定初始值但又在更新後保值不可控制,這種情況可以使用"defaultValue "
render()
{
    return(
        <form onSubmit={this.handleSubmit}>
            //使用defaultValue設定表單的value
            <label> Name:<input defaultValue="Fandix"  type="text"  ref={this.input} /></label>
        </form>
    )
}

可控組件(controlled component)

  • 在 HTML 中,表單的 element 像是 "input"、"textarea" 和 "select" 通常會維持它們自身的 state,並根據使用者的輸入來更新 state。
  • 在 React 中,可變的 state 通常是被定義在 component 中的 state property,並只能以 setState() 來更改期內容。
  • 我們可以透過將 React 的 state 變成「單一數據源」讓render表單的React component可以掌握使用者的輸入

當input的值發生改變(觸發onChange進入function "handleChange")function會將使用者輸入的值利用setState將input的state進行更改,而當onSubmit被觸發後進入function handleSubmit再將被改變的state中的Data取出。

class NameForm extends React.Component 
{
    //建立constructor
    constructor()
    {
        super();
        //綁定function的this
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    
    //設定state內容
    state = {
        value: ""
    }
    
    handleChange(event) 
    {
        //變更State的值需要使用setState
        this.setState({value: event.target.value});
    }

    handleSubmit(event) 
    {
        alert('A name was submitted: ' + this.state.value);
         //取消默認行為
        event.preventDefault();
    }
  
    render() 
    {
        return (
          <form onSubmit={this.handleSubmit}>
              <label>Name:
                  <input type="text" value={this.state.value} onChange={this.handleChange} />
              </label>
              <input type="submit" value="Submit" />
          </form>
    );
  }
}

由於 value attribute 是被設定在input上,顯示的 value 會永遠是 this.state.value,這使得 React 的 state 成為了資料來源。由於 handleChange 在每一次鍵盤被敲擊時都會被執行,並更新 React 的 state,因此被顯示的 value 將會在使用者打字的同時被更新。

處理多個輸入

當你需要處理多個 controlled input element,可以在每個 element 中加入一個 name,讓 handler function 選擇基於 event.target.name 的值進行判斷

class Reservation extends React.Component 
{
    construtor()
    {
        super();
        //綁定function的this
        this.handleInputChange = this.handleInputChange.bind(this);
    }
    
    //設定state內容
    state = {
        isGoing:true,
        numberOfGuests:2
    }
    
    handleInputChange = (event) =>{
        const target = event.target;
        const value = target.name === 'isGoing' ? target.checked : target.value;
        const name = target.name;
        
        this.setState({
            [name]:value
        });
    }
    
    render()
    {
        return(
            <form>
                <label>
                  Is going:
                  <input
                    name="isGoing"
                    type="checkbox"
                    checked={this.state.isGoing}
                    onChange={this.handleInputChange} />
                </label>
            <br />
                <label>
                    Number of guests:
                    <input
                        name="numberOfGuests"
                        type="number"
                        value={this.state.numberOfGuests}
                        onChange={this.handleInputChange} />
                </label>
          </form>
       );
    }
};

當兩個input發生改變就會進入function "handleInputChange" 判斷event.name是不是input1,若是就更新name = isGoing中的State(isGoing),若不是則更新name = "numberOfGuests"中的State(numberOfGuests)。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言